/*
 *  Copyright 2010 David Hawkes, daveh@cadlink.com
 *  Subject to the Apache License version 2.0 at http://www.apache.org/licenses/
 */

// This is the main DLL file.

#include "stdafx.h"

#include "ManagedCpp.h"

using namespace System;
using namespace IronPython::Hosting;
using namespace Microsoft::Scripting;
using namespace Microsoft::Scripting::Hosting;
using namespace System::Reflection;
using namespace DynamicAccess;

#define PY_TEST "\
import sys\n\
import ManagedCpp\n\
\n\
class PyTest(object):\n\
  def __init__(self, p1=None):\n\
    self.p1 = p1\n\
  @staticmethod\n\
  def StaticTest1():\n\
    return \"Test\"\n\
  @staticmethod\n\
  def StaticTest2(x):\n\
    return 6*x\n\
  def InstTest1(self):\n\
    return self.p1\n\
"

namespace ManagedCpp {

  void CppTesting::Test()
  {
    ScriptRuntime^ env = Python::CreateRuntime();
    ScriptEngine^ eng = Python::GetEngine(env);
    env->LoadAssembly(Assembly::GetExecutingAssembly());
    ScriptScope^ scope = env->CreateScope();
    ScriptSource^ ss = eng->CreateScriptSourceFromString(gcnew String(PY_TEST), SourceCodeKind::Statements);
    ss->Execute(scope);
    // Get the builtins dictionary
    DynWrap^ builtins = gcnew DynWrap(scope->GetVariable("__builtins__"));
    // Index it
    DynWrap^ hasattr = builtins->I("hasattr");
    // Get our test type
    DynWrap^ PyTestType = gcnew DynWrap(scope->GetVariable("PyTest"));
    // Check if it has a particular attribute
    bool bVal = hasattr->C(PyTestType, "InstTest1");
    // Call a static method
    int rtn = PyTestType->CM("StaticTest2", 10);
    // Construct an instance
    DynWrap^ PyTestInst = PyTestType->CC("xyzzy");
    // Get a member of an instance
    String^ p1 = PyTestInst->M("p1");
    // Set a member of an instance
    PyTestInst->SM("p2", 42);
    int n = PyTestInst->M("p2");
    // Remove a member
    PyTestInst->RM("p2");
    // Create a dictionary
    DynWrap^ Dict = builtins->I("dict")->CC();
    // Set an index
    Dict->SI("p5", "p5_value");
    // Get an Index
    String^ p5 = Dict->I("p5");
    // Remove an index
    Dict->RI("p5");
  }

}
